<template>
  <div class="videocall-item" v-if="showVideoCallItem">
    <div class="waiting-item" v-if="isDialing || isCalled">
      <div class="videocall-avatar">
        <Avatar :src="currentConversation.userProfile.avatar" :type="TIM.TYPES.CONV_C2C"></Avatar>
      </div>
      <div class="videocall-text">
        <p>{{ currentConversation.userProfile.nick || currentConversation.userProfile.userID }}</p>
        <span v-if="isDialing">正在等待对方接受邀请...</span>
        <span v-else-if="isCalled">邀请你视频通话...</span>
      </div>
    </div>
    <div v-show="isCalling">
      <!-- 本地画面 -->
      <div id="local" :class="isLocalMain ? 'big' : 'small'"></div>
      <!-- 远端画面 -->
      <div :id="currentConversation.userProfile.userID" :class="!isLocalMain ? 'big' : 'small'" @click="changeMainVideo"></div>
    </div>
    <div class="videocall-item-footer">
      <el-button 
        v-if="isCalling"
        @click="micHandler"
        :title="isMicOn ? '静音' : '开启声音'" 
        :icon="isMicOn ? 'el-icon-microphone': 'el-icon-turn-off-microphone'"
        circle>
      </el-button>
      <el-button v-if="isCalled" title="接听" @click="accept" type="success" icon="el-icon-phone" circle></el-button>
      <el-button 
        class="close-button" 
        @click="closeHandler"
        :title="showCloseButtonTitle" 
        type="danger" 
        icon="el-icon-phone" 
        circle>
      </el-button>
      <el-button 
        v-if="isCalling" 
        @click="camHandler"
        :title="isCamOn ? '关闭摄像头' : '打开摄像头'" 
        :icon="isCamOn ? 'el-icon-video-camera-solid' : 'el-icon-video-camera'" 
        circle>
      </el-button>
    </div>
  </div>
</template>

<script>
import { mapState } from 'vuex';
import RtcClient from '../../utils/rtcClient';
// import { STATUS } from '../../utils/trtcCustomMessageMap';
import { ACTION,VERSION,STATUS } from '../../utils/trtcCustomMessageMap';

export default {
  data(){
    return {
      isReady: false,
      isJoin: false,
      isLocalMain: true, // 本地视频是否是主屏幕显示
      isCamOn: true,
      isMicOn: true,
      timeOutTimer: 0, // 被叫方长时间未接听超时计时器
      duration: 0,
      start: 0,
      end: 0
    }
  },  
  computed:{
    ...mapState({
      videoCallStatus: state => state.videocall.videoCallStatus,
      currentConversation: state => state.conversation.currentConversation,
      userID: state => state.videocall.userID,
      userSig: state => state.videocall.userSig,
      videoRoom: state => state.videocall.videoRoom,
      sdkAppId: state => state.videocall.sdkAppId
    }),
    showVideoCallItem(){
      return this.videoCallStatus !== STATUS.VIDEO_CALL_STATUS_FREE;
    },
    isDialing(){ // 是否呼叫中
      return this.videoCallStatus === STATUS.VIDEO_CALL_STATUS_DIALING;
    },
    isCalled(){ // 是否被呼叫
      return this.videoCallStatus === STATUS.VIDEO_CALL_STATUS_CALLED;
    },
    isCalling(){ // 是否通话中
      return this.videoCallStatus === STATUS.VIDEO_CALL_STATUS_CALLING;
    },
    showCloseButtonTitle(){
      switch(this.videoCallStatus){
        case STATUS.VIDEO_CALL_STATUS_DIALING:
          return '取消';
        case STATUS.VIDEO_CALL_STATUS_CALLED:
          return '拒绝';
        default:
          return '挂断';
      }
    }
  },
  watch:{
    videoCallStatus(next){
      // 监听视频通话状态，当进入通话状态或被呼叫状态，且尚未初始化成功时，进行trtc初始化
      switch(next){
        case STATUS.VIDEO_CALL_STATUS_DIALING:
        case STATUS.VIDEO_CALL_STATUS_CALLED:
          this.initVideoCall();
          break;
        case STATUS.VIDEO_CALL_STATUS_CALLING: // 对方接通或己方接受后，进入视频通话
          this.videoCall();
          break;
        case STATUS.VIDEO_CALL_STATUS_FREE:
          if(this.timeOutTimer !== 0){
            clearTimeout(this.timeOutTimer);
          }
          break;
      }
    }
  },
  methods:{
    initVideoCall(){
      const options = {
        userId: this.userID,
        userSig: this.userSig,
        roomId: this.videoRoom,
        sdkAppId: this.sdkAppId
      }
      this.initTrtc(options).then(() => {
        if (!this.isReady) {
          this.$store.commit('toggleVideoCallStatus', STATUS.VIDEO_CALL_STATUS_FREE);
          this.sendVideoMessage(ACTION.VIDEO_CALL_ACTION_ERROR);
          return;
        }
        if(this.isDialing){
          this.timeOutTimer = setTimeout(this.timeout, 60000); // 60秒未接通电话则判断为超时
        }
      });
    },
    async initTrtc(options) { // 初始化 trtc 进入房间
      this.Trtc = new RtcClient(options);
      await this.Trtc.createLocalStream({ audio: true, video: true }).then(() => { // 在进房之前，判断设备
        this.isReady = true;
        this.isCamOn = true;
        this.isMicOn = true;
        if(this.isCalling){ // 初始化完成后，若已经为通话中的状态，则进入通话；场景：尚未初始化完成用户已经同意通话
          this.videoCall();
        }
      }).catch(() => {
        this.$store.commit('showMessage', { message: '请确认已连接摄像头和麦克风并授予其访问权限！' , type: 'error' });
        this.isReady = false;
      });
    },
    videoCall() {
      if(this.isReady){
        this.Trtc.join();
        this.isJoin = true;
        this.start = new Date();
      }
    },
    timeout() { // 通话超时
      if(this.isJoin){
        this.Trtc.leave();
        this.isJoin = false;
      }
      this.sendVideoMessage(ACTION.VIDEO_CALL_ACTION_SPONSOR_TIMEOUT);
      this.$store.commit('toggleVideoCallStatus', STATUS.VIDEO_CALL_STATUS_FREE);
    },
    accept(){
      // 这里只发送接听消息和改变为通话中状态，在watch监听到状态后执行进房操作
      this.sendVideoMessage(ACTION.VIDEO_CALL_ACTION_ACCEPTED);
      this.$store.commit('toggleVideoCallStatus', STATUS.VIDEO_CALL_STATUS_CALLING);
    },
    changeMainVideo(){
      this.isLocalMain = !this.isLocalMain;
    },
    camHandler(){
      if(this.isCamOn){
        this.Trtc.muteLocalVideo();
      } else {
        this.Trtc.unmuteLocalVideo();
      }
      this.isCamOn = !this.isCamOn;
    },
    micHandler(){
      if(this.isMicOn){
        this.Trtc.muteLocalAudio();
      } else {
        this.Trtc.unmuteLocalAudio();
      }
      this.isMicOn = !this.isMicOn;
    },
    closeHandler(){
      if(this.isDialing){ // 呼叫中，单方面挂断
        clearTimeout(this.timeOutTimer);
        this.sendVideoMessage(ACTION.VIDEO_CALL_ACTION_SPONSOR_CANCEL);
      } else if(this.isCalled){ // 被呼叫中，拒绝通话
        this.sendVideoMessage(ACTION.VIDEO_CALL_ACTION_REJECT);
      } else { // 通话中，挂断电话
        this.end = new Date();
        const duration = parseInt((this.end - this.start) / 1000);
        this.sendVideoMessage(ACTION.VIDEO_CALL_ACTION_HANGUP, duration);
      }
      if(this.join){
        this.Trtc.leave();
        this.join = false;
      }
      this.$store.commit('toggleVideoCallStatus', STATUS.VIDEO_CALL_STATUS_FREE);
    },
    sendVideoMessage(action, duration = 0) {
      const options = {
        room_id: this.videoRoom,
        action: action,
        type: this.currentConversation.type,
        duration: duration,
        version: VERSION
      }
      const message = this.tim.createCustomMessage({
        to: this.currentConversation.userProfile.userID,
        conversationType: this.currentConversation.type,
        payload: {
          data: 'video_call',
          description: '',
          extension: JSON.stringify(options)
        }
      });
      this.$store.dispatch('sendMessage', message);
    }
  }
}
</script>

<style scoped>
.videocall-item{
  position: relative;
  background-color: rgba(0,0,0,0.8);
  width: 100%;
  height: 100%;
}
.waiting-item, .videocall-item-footer{
  text-align: center;
}
.videocall-text p {
  color: white;
  font-size: 22px;
  line-height: 30px;
}
.videocall-text span{
  color: #aaaaaa;
  font-size: 14px;
  line-height: 22px;
}
.videocall-avatar{
  margin: 40px auto;
  height: 160px;
  width: 160px;
}
.videocall-item-footer{
  position: absolute;
  width: 100%;
  bottom: 40px;
}
.videocall-item-footer .el-button{
  width: 60px;
  height: 60px;
  font-size: 26px;
  margin: 20px;
  z-index: 20;
}
.close-button{
  transform:rotate(134deg);
}
.big{
  position: absolute;
  width: 100%;
  height: 100%;
}
.small{
  position: absolute;
  left: 74.8%;
  z-index: 999;
  border-style: solid;
  border-width: 1px;
  border-color: #808080;
  height :44.8%;
  width: 25.2%;
}
</style>